package io.gitee.macxiang.utils;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import com.alibaba.fastjson2.JSONObject;

/** 网络相关,发起get/post请求 */
public class Http extends Mime {
  /**转化json格式为URL方式的参数
   * @param url     请求地址
   * @param params  参数
   * @return        将参数拼接成URL后返回
   */
  private static String urlParam(String url, JSONObject params) {
    if (params != null) {
      List<String> sa = new ArrayList<>();
      for (String key : params.keySet()) {
        sa.add(key + "=" + URLEncoder.encode(params.getString(key), StandardCharsets.UTF_8));
      }
      if (sa.size() > 0) {
        url += (url.indexOf('?', 0) > 0 ? "&" : "?") + String.join("&", sa);
      }
    }
    return url;
  }

  /**执行get方法
   * @param getUrl  请求地址
   * @param params  请求参数
   * @param header  附加请求头
   * @return        请求结果
   */
  public static byte[] get(String getUrl, JSONObject params, JSONObject header) {
    HttpURLConnection httpURLConnection = null;
    byte[] ret = null;
    try {
      // 1. 得到访问地址的URL
      URL url = new URI(urlParam(getUrl, params)).toURL();
      // 2. 得到网络访问对象java.net.HttpURLConnection
      httpURLConnection = (HttpURLConnection) url.openConnection();
      /* 3. 设置请求参数（过期时间，输入、输出流、访问方式），以流的形式进行连接 */
      // 设置是否向HttpURLConnection输出
      httpURLConnection.setDoOutput(false);
      // 设置是否从httpUrlConnection读入
      httpURLConnection.setDoInput(true);
      // 设置请求方式 默认为GET
      httpURLConnection.setRequestMethod("GET");
      // 设置是否使用缓存
      httpURLConnection.setUseCaches(true);
      // 设置此 HttpURLConnection 实例是否应该自动执行 HTTP 重定向
      httpURLConnection.setInstanceFollowRedirects(true);
      // 设置超时时间
      httpURLConnection.setConnectTimeout(3000);
      // 设置请求头
      if (header != null) {
        for (Map.Entry<String, Object> entry : header.entrySet()) {
          httpURLConnection.addRequestProperty(entry.getKey(), entry.getValue().toString());
        }
      }

      // 连接
      httpURLConnection.connect();
      // 4. 得到响应状态码的返回值 responseCode
      int code = httpURLConnection.getResponseCode();
      // 5. 如果返回值正常，数据在网络中是以流的形式得到服务端返回的数据
      InputStream inputStream = code == 200 ? httpURLConnection.getInputStream() : httpURLConnection.getErrorStream();
      byte[] buff = new byte[4096];
      int len;
      ByteArrayOutputStream os = new ByteArrayOutputStream();
      while ((len = inputStream.read(buff)) > 0) {
        os.write(buff, 0, len);
      }
      // 6. 断开连接，释放资源
      if (null != httpURLConnection) {
        try {
          httpURLConnection.disconnect();
        } catch (Exception e) {
          System.out.println("httpGet:httpURLConnection 流关闭异常：" + e.getLocalizedMessage());
        }
      }
      ret = os.toByteArray();
    } catch (Exception e) {
      throw new RuntimeException("httpGet:转发出错，错误信息：" + e.getLocalizedMessage() + ";" + e.getClass());
    } finally {
      // 6. 断开连接，释放资源
      if (null != httpURLConnection) {
        try {
          httpURLConnection.disconnect();
        } catch (Exception ee) {
          System.out.println("httpGet:httpURLConnection 流关闭异常：" + ee.getLocalizedMessage());
        }
      }
    }
    return ret;
  }

  /**执行get方法
   * @param url     请求地址
   * @param params  请求参数
   * @param header  附加请求头
   * @return        请求结果
   */
  public static String getString(String url, JSONObject params, JSONObject header) {
    return Datas.b2s(get(url, params, header));
  }

  /**执行get方法
   * @param url     请求地址
   * @param params  请求参数
   * @param header  附加请求头
   * @return        请求结果
   */
  public static JSONObject getJson(String url, JSONObject params, JSONObject header) {
    return Datas.toJsonObject(getString(url, params, header));
  }

  /**执行get方法
   * @param url     请求地址
   * @param params  请求参数
   * @return        请求结果
   */
  public static byte[] get(String url, JSONObject params) {
    return get(url, params, null);
  }

  /**执行get方法
   * @param url     请求地址
   * @param params  请求参数
   * @return        请求结果
   */
  public static String getString(String url, JSONObject params) {
    return Datas.b2s(get(url, params));
  }

  /**执行get方法
   * @param url     请求地址
   * @param params  请求参数
   * @return        请求结果
   */
  public static JSONObject getJson(String url, JSONObject params) {
    return Datas.toJsonObject(getString(url, params));
  }

  /**执行get方法
   * @param url 请求地址
   * @return    请求结果
   */
  public static byte[] get(String url) {
    return get(url, null, null);
  }

  /**执行get方法
   * @param url 请求地址
   * @return    请求结果
   */
  public static String getString(String url) {
    return Datas.b2s(get(url, null, null));
  }

  /**执行get方法
   * @param url 请求地址
   * @return    请求结果
   */
  public static JSONObject getJson(String url) {
    return Datas.toJsonObject(getString(url, null, null));
  }

  /**执行post方法
   * @param postUrl 请求地址
   * @param params  请求参数
   * @param header  附加请求头
   * @return        请求结果
   */
  public static byte[] post(String postUrl, JSONObject params, JSONObject header) {
    HttpURLConnection httpURLConnection = null;
    byte[] ret = null;
    try {
      // 1. 获取访问地址URL
      // URL url = new URL("http://localhost:8080/Servlet/do_login.do");
      URL url = new URI(postUrl).toURL();
      // 2. 创建HttpURLConnection对象
      httpURLConnection = (HttpURLConnection) url.openConnection();
      /* 3. 设置请求参数等 */
      // 请求方式 默认 GET
      httpURLConnection.setRequestMethod("POST");
      // 超时时间
      httpURLConnection.setConnectTimeout(3000);
      // 设置是否输出
      httpURLConnection.setDoOutput(true);
      // 设置是否读入
      httpURLConnection.setDoInput(true);
      // 设置是否使用缓存
      httpURLConnection.setUseCaches(false);
      // 设置此 HttpURLConnection 实例是否应该自动执行 HTTP 重定向
      httpURLConnection.setInstanceFollowRedirects(true);
      if (header == null) {
        header = new JSONObject();
      }
      // if (!header.containsKey("sysId")) {
      // header.put("sysId", "sysId");
      // }
      if (!header.containsKey("Content-Type")) {
        header.put("Content-Type", "application/x-www-form-urlencoded");
      }
      // 设置请求头
      for (Map.Entry<String, Object> entry : header.entrySet()) {
        httpURLConnection.addRequestProperty(entry.getKey(), entry.getValue().toString());
      }

      // 连接
      httpURLConnection.connect();
      /* 4. 处理输入输出 */
      // 写入参数到请求中
      OutputStream out = httpURLConnection.getOutputStream();
      if (params != null) {
        out.write(params.toJSONString().getBytes());
      }
      // 简化
      // httpURLConnection.getOutputStream().write(params.getBytes());
      out.flush();
      out.close();
      // 从连接中读取响应信息
      int code = httpURLConnection.getResponseCode();
      InputStream inputStream = code == 200 ? httpURLConnection.getInputStream() : httpURLConnection.getErrorStream();
      byte[] buff = new byte[4096];
      int len;
      if (code != 200) {
        System.out.println("POST错误码:" + code);
      }
      ByteArrayOutputStream os = new ByteArrayOutputStream();
      while ((len = inputStream.read(buff)) > 0) {
        os.write(buff, 0, len);
      }
      ret = os.toByteArray();
    } catch (Exception e) {
      System.out.println("httpPost:转发出错，错误信息：" + e.getLocalizedMessage());
    } finally {
      // 5. 断开连接
      if (null != httpURLConnection) {
        try {
          httpURLConnection.disconnect();
        } catch (Exception e) {
          System.out.println("httpPost:httpURLConnection 流关闭异常：" + e.getLocalizedMessage());
        }
      }
    }
    return ret;
  }

  /**执行post方法
   * @param url     请求地址
   * @param params  请求参数
   * @param header  附加请求头
   * @return        请求结果
   */
  public static String postString(String url, JSONObject params, JSONObject header) {
    return Datas.b2s(post(url, params, header));
  }

  /**执行post方法
   * @param url     请求地址
   * @param params  请求参数
   * @param header  附加请求头
   * @return        请求结果
   */
  public static JSONObject postJson(String url, JSONObject params, JSONObject header) {
    return Datas.toJsonObject(postString(url, params, header));
  }

  /**执行post方法
   * @param url     请求地址
   * @param params  请求参数
   * @return        请求结果
   */
  public static byte[] post(String url, JSONObject params) {
    return post(url, params, null);
  }

  /**执行post方法
   * @param url     请求地址
   * @param params  请求参数
   * @return        请求结果
   */
  public static String postString(String url, JSONObject params) {
    return Datas.b2s(post(url, params, null));
  }

  /**执行post方法
   * @param url 请求地址
   * @param params  请求参数
   * @return        请求结果
   */
  public static JSONObject postJson(String url, JSONObject params) {
    return Datas.toJsonObject(postString(url, params));
  }

  /**执行post方法
   * @param url     请求地址
   * @return        请求结果
   */
  public static byte[] post(String url) {
    return post(url, null, null);
  }

  /**执行post方法
   * @param url 请求地址
   * @return        请求结果
   */
  public static String postString(String url) {
    return Datas.b2s(post(url, null, null));
  }

  /**执行post方法
   * @param url 请求地址
   * @return        请求结果
   */
  public static JSONObject postJson(String url) {
    return Datas.toJsonObject(postString(url));
  }

}
